<?
	Class HTML extends Base {

		private $values = array();
		private $elems = array();
		
		function buildForm($params=array(),$table="") {
			
			$model = Model::Load("$table/{$table}Model");

			if($params['attrs']['method']) {
				$method = $params['attrs']['method'];
			} else $method=$params['attrs']['method']="POST";
			
			$this->values=Request::S()->$method?(object)Request::S()->$method:View::S()->$table;

			if($table&&!$params['attrs']['name']) $formAttrs['name'] = "form_$table"; else $formAttrs=array();
			if($params['attrs']) $formAttrs = array_merge($formAttrs,$params['attrs']);
			
			$form = $this->form($formAttrs);
			
			if($table) {
				$dbfields = DB::S()->GetTableCols($model->table);
				if(is_bool($model->fk)) $model->fk = DB::S()->GetFK($model->table);

				foreach($dbfields as $field) {
				
					if(is_array($params['remove'])&&in_array($field->name,$params['remove'])) continue;

					$continue=false;

					/* нужно проверить, передан ли параметр соответствий для таблиц с foreign key,
					или поискать служебную таблицу в БД */
					$xrefTable = DB::S()->GetTable($model->_prefix."xref");
					if($params['xref']||($model->fk && $xrefTable)) foreach($model->fk as $fk) {
						if($fk->from==$field->name) {
							$fk_to = $params['xref'][$fk->from]?$params['xref'][$fk->from]:$model->ReadSql("SELECT xref_to FROM ".$model->_prefix."xref WHERE xref_from='$field->name' ORDER BY xref_id DESC LIMIT 0,1")[0]->xref_to;

							$SelectFunc = isset($params['append'][$field->name]['type'])?'input':'select';
							if($SelectFunc=='select') {
								$label = $this->label(array('text'=>"__".$fk_to));
								$this->addElement($label);
								$select_element = $this->$SelectFunc(array('name'=>$field->name));
							}
							
							if($SelectFunc=='select') {
								$optParams = array('value'=>'','text'=>'__not_selected');
								$option = $this->option($optParams);
								$select_element->inject($option);
							}
							foreach($model->ReadSql("SELECT * FROM $fk->table") as $row) {
								//var_dump($row,$fk->from,$fk_to);
								if($fk->from&&$fk_to) {
									$value = $row->{$fk->from}?$row->{$fk->from}:$row->{substr($fk->from,strpos($fk->from,'_')+1)};
									
									if($SelectFunc=='select') {
										$optParams = array('value'=>$value,'text'=>$row->$fk_to);
										if($this->values->{$field->name}==$value) $optParams['selected']='selected';
										$option = $this->option($optParams);
										$select_element->inject($option);
									} else {
										$optParams = array('name'=>$field->name,'type'=>$params['append'][$field->name]['type'],'value'=>$value);
										if($this->values->{$field->name}==$value) $optParams['checked']='checked';
										$this->addElement($this->$SelectFunc($optParams));
										$this->addElement($this->label(array('text'=>$row->$fk_to)));
									}
								}
							}
							
							if($SelectFunc=='select') $this->addElement($select_element,$params['append'][$field->name]['sort']);
							$continue=true;
						} 
					}
					
					if($continue) {if($params['append'][$field->name]) unset($params['append'][$field->name]);continue;}
					
					switch ($field->type) {

						case ($field->pk ? true : false):
							$this->addElement($this->input(array('type'=>($params['append'][$field->name]['type']?$params['append'][$field->name]['type']:'hidden'),
								'name'=>$field->name,'value'=>$this->values->{$field->name},'placeholder'=>($params['append'][$field->name]?"__".$field->name:''))));
						break;
						case (preg_match('/text|integer.*/i', $field->type) ? true : false):
							if($params['append'][$field->name]['label']) $this->addElement($this->label($params['append'][$field->name]['label']),$params['append'][$field->name]['sort']);
							if($params['append'][$field->name]['type']=='textarea') {
								$this->addElement($this->textarea(
									array('name'=>$field->name,'text'=>$this->values->{$field->name},'placeholder'=>'__'.$field->name)
									),$params['append'][$field->name]['sort']);
							} else {
								$label = $params['append'][$field->name]['type']=='hidden'?'':"__".$field->name;
								$this->addElement($this->input(array_merge(array('type'=>'text',
									'name'=>$field->name,
									'value'=>$this->values->{$field->name},
									'placeholder'=>$label),(array)$params['append'][$field->name])
									),$params['append'][$field->name]['sort']);
							}
						break;
						
						
					}
					if($params['append'][$field->name]) unset($params['append'][$field->name]);
					
				}
			}
			
			if(is_array($params['append'])) foreach($params['append'] as $kf=>$field) {
				if($params['append'][$kf]['label']) $this->addElement($this->label($params['append'][$field->name]['label']),$params['append'][$kf]['sort']);
				$this->addElement($this->input(
					array_merge(array('name'=>$kf,'value'=>$this->values->$kf,'placeholder'=>'__'.$kf),$field)
					),$params['append'][$kf]['sort']);
			}
			
			if($params['genToken']) $this->addElement($this->renderToken(),110);
			
			if(isset($params['submit'])) {
				foreach($params['submit'] as $submit) $this->addElement($this->button($submit),111);
			}
			else $this->addElement($this->button(array('text'=>'__submit')),111);
			
			foreach($this->elems as $elem) {
				$div = $this->div();
				$div->set('class','element '.$elem->get('name'));
				$div->inject($elem);
				$form->inject($div);
			}

			return $form->build();
		}

		function renderToken($token) {
			return $this->input(array('type'=>'hidden','name'=>'token','value'=>$token));
		}

		private function addElement($element,$sort=0) {
			$this->array_insert($this->elems,$sort,$element);
		}

		private function array_insert(&$array, $position, $element) { 
			if($position) {
				$first_array = array_splice($array, 0, $position);
				$first_array[$position] = $element;
				$array=array_merge($first_array,$array);
			}
		   else $array[]=$element;
		}


		public function __call($method,$arguments) {
			$tag = new html_element($method);
			if($arguments[0]) {
				if(is_array($arguments[0])) $tag->set($arguments[0]);
				else $tag->set('text',$arguments[0]);
			}
			return $tag;
		}
		
		// рендеринг списков: в виде блога или таблицы
		function listing($items, $params=array()) {
			$table = Router::S()->getRoute()['controllerName'];
			$model = Model::Load("$table/{$table}Model");
			if($items) {
				switch($params['listing']['type']) {
					case "table":
						$table = $this->table();
						$thead = $this->thead();
						$tr = $this->tr();
						
						foreach($items as $item) foreach($item as $k=>$it) $ks[$k]=$k;
						foreach($ks as $k=>$it) {
							if($params&&in_array($k,$params['listing']['remove'])) continue;
							$tr->inject($this->th(array('scope'=>'col','text'=>"__".$k)));
						}
						$thead->inject($tr);
						$table->inject($thead);
						$tbody = $this->tbody();
						
						foreach($items as $item) {
							$tr = $this->tr();
							foreach((array)$params['listing']['links'] as $klink=>$link) {
								$_kl = explode('_',$klink);
								if(class_exists($_kl[0].'Controller')) $item->$link = $this->a(
									array('href'=>__SITE_LIVE."{$_kl[0]}/read/{$item->$klink}",
									'text'=>$item->$link)
									)->build();
							}
							foreach($item as $k=>$it) {
								if($params&&in_array($k,(array)$params['listing']['remove'])) continue;
								$tr->inject($this->td(array('class'=>"$k",'text'=>$it)));
							}
							$tbody->inject($tr);
						}
						$table->inject($tbody);
						$table->output();
					break;
					default:
						foreach($items as $item) {
							
							$dItem = $this->div(array('class'=>'item'));
							foreach((array)$params['listing']['links'] as $klink=>$link) {
								$_kl = explode('_',$klink);
								if(class_exists($_kl[0].'Controller')) $item->$link = $this->a(
									array('href'=>__SITE_LIVE."{$_kl[0]}/read/{$item->$klink}",
									'text'=>$item->$link)
									)->build();
								unset($item->$klink);
							}
							foreach($item as $k=>$it) {
								if($params&&in_array($k,(array)$params['listing']['remove'])) continue;
								$dItem->inject($this->div(array('class'=>$k,'text'=>$it)));
							}
							$dItem->output();
						}
				}

				/*пагинация, сортировка и фильтрация
				пагинация показывается всегда, если у модели не задано свойство pagination=false,
				сортировка и фильтрация - только, если явно указаны true*/
				if(isset($model->pagination)&&!$model->pagination) {}
				else $this->pagination($model);
				if($model->sorting&&View::S()->params['sorting']!==false) {
					$this->sorting($items);
				}
			} else echo '__no_items_found';
			if($model->filtering&&View::S()->params['filtering']!==false) $this->filtering();
		}

		/*function pagination($model) {
			
		}*/

		function pagination($model) {
			$paging = $model->pagination;
			
			$vsego = ceil($paging['count']/$paging['onpage']);
			if(strpos(Uri::S()->path,'&')!==false) $filterQuery = substr(Uri::S()->path,strpos(Uri::S()->path,'&'));
			if($paging['start']) {
				$first = $this->a(array('href'=>"/".Router::S()->getRoute()['controllerName'].$filterQuery,'text'=>'__first_page'));
			} else {
				$first = $this->span('__first_page');
			}

			for($i=0;$i<$paging['count'];$i+=$paging['onpage']){
				$pnum=$i/$paging['onpage']+1;
				if($i==$paging['start']){
					$page = $this->span(array('class'=>"active",'text'=>$pnum));
				}else{
					$page = $this->a(array('href'=>'/'.($i?implode("/",Router::S()->getRoute()):Router::S()->getRoute()['controllerName'].'/').($i?"/$i":'').$filterQuery,'text'=>$pnum));
				}
				$pages.=$page->build();
			}
			if($paging['start']+$paging['onpage']<$paging['count']){
				$last = $this->a(array('href'=>'/'. implode("/",Router::S()->getRoute()).'/'.($vsego*$paging['onpage']-$paging['onpage']).$filterQuery,'text'=>'__last_page'));
			}else{
				$last = $this->span('__last_page');
			}
			$pagesline = $first->build();
			$pagesline .= $pages;
			$pagesline .= $last->build();
			$paging['pages'] = $pagesline;

			View::S()->paging = $paging;
			
			echo View::S()->fetch('pagination');
		}

		function sorting($items) {
			$table = Router::S()->getRoute()['controllerName'];
			$model = Model::Load("$table/{$table}Model");
			$info = $model->ReadSql("PRAGMA table_info($model->table)");
			foreach($info as $infrow) {
				if($infrow->pk) {
					$options["$infrow->name DESC"] = "__".$infrow->name."_desc";
					$options["$infrow->name ASC"] = "__".$infrow->name."_asc";
				}
			}
			foreach(reset($items) as $k=>$it) {
				$options["$k DESC"] = "__".$k."_desc";
				$options["$k ASC"] = "__".$k."_asc";
			}
			View::S()->sortoptions = $options;
			echo View::S()->fetch('sort');
		}

		function filtering() {
			$route = Router::S()->getRoute();
			View::S()->filterForm = $this->buildForm(array(
				'attrs'=>array('method'=>'GET','action'=>'/'.implode("/",$route)),
				'submit'=>array(array('text'=>'__filter'))),$route['controllerName']);
			echo View::S()->fetch('filter');
		}

		function controls() {
			$table = Router::S()->getRoute()['controllerName'];
			if(Users::S()->acl->allowed($table.'/updateOwn')||Users::S()->acl->allowed($table.'/update')) {
				if(!is_array(View::S()->$table)) View::S()->$table = array(View::S()->$table);
				foreach(View::S()->$table as &$item) {
					$modify = $this->span(array('class'=>'sModify'));
					if(Users::S()->id==$item->users_id||Users::S()->acl->allowed($table.'/update')) {
						$modify->inject($this->a(array('href'=>'/'.$table.'/update/'.$item->{$table."_id"},'class'=>"table-icon edit", "title"=>"__edit_item")));
						$modify->inject($this->a(array('href'=>'/'.$table.'/read/'.$item->{$table."_id"},'class'=>"table-icon archive", "title"=>"__show_item")));
						
					}
					if(Users::S()->acl->allowed($table.'/delete')||
						(Users::S()->acl->allowed($table.'/deleteOwn')&&Users::S()->id==$item->users_id)) {
							$modify->inject($this->a(array('href'=>'/'.$table.'/delete/'.$item->{$table."_id"},'class'=>"table-icon delete", "title"=>"__delete_item")));
					}
					$item->modify = $modify->build();
				}
				//это для страницы просмотра материала
				return $item->modify;
			}
		}

//TO DO: это нужно будет удалить 

		/* создание атрибутов для элементов формы
		private static function genAttrs($attrs=array()) {
			foreach($attrs as $k=>$attr) {
				if(is_array($attr)) $output.=self::genAttrs($attr);
				else $output.="$k=\"$attr\" ";
			}
			return $output;
		}*/
		
		/*static function input($attrs=array(),$label='') {
			$output = self::genAttrs($attrs);
			if($label) $label="<label>$label</label>";
			return "$label <input $output />";
		}
		
		static function select($options,$selected='',$attrs=array(),$label='') {
			$output = self::genAttrs($attrs);
			if($label) $label="<label>$label</label>";
			$output = "$label <select $output>";
			foreach($options as $k=>$option) $output .= "<option value=\"$k\"".($selected&&$selected==$k?' selected':'').">$option</option>";
			
			return $output."</select>";
		}

		static function radio($options,$selected='',$attrs=array(),$label='') {
			$attrs = self::genAttrs($attrs);
			if($label) $label="<label>$label</label>";
			$output = "$label";
			foreach($options as $k=>$option) $output .= "<input value=\"$k\"".($selected&&$selected==$k?' selected':'')." type=\"radio\" $attrs /> $option";
			
			return $output;
		}

		static function button($attrs=array(),$label='') {
			$output = self::genAttrs($attrs);
			return "<button $output>{$attrs['value']}</button>";
		}

		static function textarea($attrs=array(),$label='') {
			$output = self::genAttrs($attrs);
			if($label) $label="<label>$label</label>";
			return "$label <textarea $output>{$attrs['value']}</textarea>";
		}*/

	}
?>
